/*
 * Copyright © 2025 上海火金网络科技有限公司. All rights reserved.
 *
 * ✅ MANUAL FILE - CAN BE MODIFIED 手动文件 - 可以修改 ✅
 */

package cn.com.anypay.manager.common.utils;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.function.Function;

/**
 * Excel导出工具类
 * 提供通用的Excel文件导出功能
 */
public final class ExcelExportUtil {

    private static final Logger logger = LoggerFactory.getLogger(ExcelExportUtil.class);

    // 防止实例化
    private ExcelExportUtil() {
        throw new UnsupportedOperationException("Utility class cannot be instantiated");
    }

    /**
     * 导出Excel文件到HTTP响应
     *
     * @param data 要导出的数据列表
     * @param headers 表头数组
     * @param dataExtractor 数据提取函数，将数据对象转换为字符串数组
     * @param fileName 文件名（不包含扩展名）
     * @param sheetName 工作表名称
     * @param response HTTP响应对象
     * @param <T> 数据类型
     */
    public static <T> void exportToResponse(List<T> data, String[] headers, 
                                          Function<T, String[]> dataExtractor,
                                          String fileName, String sheetName,
                                          HttpServletResponse response) {
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet(sheetName);
            
            // 创建标题行样式
            CellStyle headerStyle = createHeaderStyle(workbook);
            
            // 创建标题行
            createHeaderRow(sheet, headers, headerStyle);
            
            // 填充数据
            fillDataRows(sheet, data, dataExtractor);
            
            // 自动调整列宽
            autoSizeColumns(sheet, headers.length);
            
            // 设置响应头并写入文件
            setResponseHeaders(response, fileName);
            workbook.write(response.getOutputStream());
            
            logger.info("Excel文件导出成功: {}, 数据行数: {}", fileName, data.size());
            
        } catch (IOException e) {
            logger.error("Excel文件导出失败: {}", fileName, e);
            throw new RuntimeException("Excel文件导出失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建带时间戳的文件名
     *
     * @param baseName 基础文件名
     * @return 带时间戳的文件名
     */
    public static String createTimestampFileName(String baseName) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        return baseName + "_" + timestamp + ".xlsx";
    }

    /**
     * 创建标题行样式
     */
    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle headerStyle = workbook.createCellStyle();
        Font headerFont = workbook.createFont();
        headerFont.setBold(true);
        headerFont.setFontHeightInPoints((short) 12);
        headerStyle.setFont(headerFont);
        
        // 设置背景色
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        
        // 设置边框
        headerStyle.setBorderTop(BorderStyle.THIN);
        headerStyle.setBorderBottom(BorderStyle.THIN);
        headerStyle.setBorderLeft(BorderStyle.THIN);
        headerStyle.setBorderRight(BorderStyle.THIN);
        
        // 设置对齐方式
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        
        return headerStyle;
    }

    /**
     * 创建数据行样式
     */
    private static CellStyle createDataStyle(Workbook workbook) {
        CellStyle dataStyle = workbook.createCellStyle();
        
        // 设置边框
        dataStyle.setBorderTop(BorderStyle.THIN);
        dataStyle.setBorderBottom(BorderStyle.THIN);
        dataStyle.setBorderLeft(BorderStyle.THIN);
        dataStyle.setBorderRight(BorderStyle.THIN);
        
        // 设置对齐方式
        dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        
        return dataStyle;
    }

    /**
     * 创建标题行
     */
    private static void createHeaderRow(Sheet sheet, String[] headers, CellStyle headerStyle) {
        Row headerRow = sheet.createRow(0);
        headerRow.setHeight((short) 500); // 设置行高
        
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }
    }

    /**
     * 填充数据行
     */
    private static <T> void fillDataRows(Sheet sheet, List<T> data, Function<T, String[]> dataExtractor) {
        Workbook workbook = sheet.getWorkbook();
        CellStyle dataStyle = createDataStyle(workbook);
        
        for (int i = 0; i < data.size(); i++) {
            Row row = sheet.createRow(i + 1);
            T item = data.get(i);
            String[] rowData = dataExtractor.apply(item);
            
            for (int j = 0; j < rowData.length; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue(rowData[j] != null ? rowData[j] : "");
                cell.setCellStyle(dataStyle);
            }
        }
    }

    /**
     * 自动调整列宽
     */
    private static void autoSizeColumns(Sheet sheet, int columnCount) {
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i);
            // 设置最大列宽，防止列宽过大
            int columnWidth = sheet.getColumnWidth(i);
            if (columnWidth > 15000) { // 约75个字符宽度
                sheet.setColumnWidth(i, 15000);
            }
        }
    }

    /**
     * 设置HTTP响应头
     */
    private static void setResponseHeaders(HttpServletResponse response, String fileName) throws IOException {
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
        
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", "0");
    }

    /**
     * 批量导出大数据量（分批处理）
     *
     * @param dataProvider 数据提供者函数，接收页码和页大小，返回数据列表
     * @param totalCount 总数据量
     * @param batchSize 批处理大小
     * @param headers 表头数组
     * @param dataExtractor 数据提取函数
     * @param fileName 文件名
     * @param sheetName 工作表名称
     * @param response HTTP响应对象
     * @param <T> 数据类型
     */
    public static <T> void exportLargeDataToResponse(Function<Integer, List<T>> dataProvider,
                                                   int totalCount, int batchSize,
                                                   String[] headers, Function<T, String[]> dataExtractor,
                                                   String fileName, String sheetName,
                                                   HttpServletResponse response) {
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet(sheetName);
            
            // 创建标题行样式
            CellStyle headerStyle = createHeaderStyle(workbook);
            CellStyle dataStyle = createDataStyle(workbook);
            
            // 创建标题行
            createHeaderRow(sheet, headers, headerStyle);
            
            // 分批处理数据
            int currentRow = 1;
            int batchCount = (totalCount + batchSize - 1) / batchSize;
            
            for (int batch = 0; batch < batchCount; batch++) {
                List<T> batchData = dataProvider.apply(batch);
                
                for (T item : batchData) {
                    Row row = sheet.createRow(currentRow++);
                    String[] rowData = dataExtractor.apply(item);
                    
                    for (int j = 0; j < rowData.length; j++) {
                        Cell cell = row.createCell(j);
                        cell.setCellValue(rowData[j] != null ? rowData[j] : "");
                        cell.setCellStyle(dataStyle);
                    }
                }
                
                // 记录进度
                logger.debug("Excel导出进度: {}/{} 批次完成", batch + 1, batchCount);
            }
            
            // 自动调整列宽
            autoSizeColumns(sheet, headers.length);
            
            // 设置响应头并写入文件
            setResponseHeaders(response, fileName);
            workbook.write(response.getOutputStream());
            
            logger.info("大数据量Excel文件导出成功: {}, 总数据行数: {}", fileName, totalCount);
            
        } catch (IOException e) {
            logger.error("大数据量Excel文件导出失败: {}", fileName, e);
            throw new RuntimeException("Excel文件导出失败: " + e.getMessage(), e);
        }
    }
}